const path = require('path');
const fs = require('fs');
const os = require('os');
const Busboy = require('busboy');
const {responseErr, responseSuc} = require("../utils/app/response");
const fileService = require("../services/fileService");
const {promisify} = require("util");
const {parseFormData, streamPipeline} = require("../utils/util");
const formidable = require("formidable");
const stream = require("stream");
const multiparty = require('multiparty');
const url = require("url");
// 文件上传接口
let uploadDir = "/public/uploads/chunk/"
let fileDir="/public/uploads/file"
const uploadFileSlice = async (ctx) => {
    const file_hash = ctx.get("fileHash")
    const chunk_index = ctx.get("chunkIndex")
    // 创建 multiparty 解析器
    const form = new multiparty.Form();
    // 使用 Promise 来处理文件上传
    const upload = new Promise((resolve, reject) => {
        form.parse(ctx.req, (err, fields, files) => {
            if (err) {
                reject(err);
            } else {
                resolve({fields, files});
            }
        });
    });

    try {
        const {fields, files} = await upload;
        const file = files.file[0]; // 这里上传字段名是 "file"
        const tempFilePath = file.path; // 临时文件路径
        // 你可以将文件保存到你想要的位置

        const targetDir = path.join(process.cwd(), uploadDir, file_hash); // 目标目录
        const targetPath = path.join(targetDir, file_hash + '' + chunk_index);
        const outPath = uploadDir + file_hash + '' + chunk_index
        // 检查目标目录是否存在，如果不存在则创建它
        if (!fs.existsSync(targetDir)) {
            fs.mkdirSync(targetDir, {recursive: true}); // 创建目录
        }
        // 复制文件到目标目录
        fs.copyFileSync(tempFilePath, targetPath);
        // 删除临时文件
        fs.unlinkSync(tempFilePath);
        // responseSuc({ctx: ctx, data: {url: ""}})
        let {err} = await fileService.insertSliceFile({file_hash, chunk_index, url: outPath})
        if (err) {
            responseErr({ctx: ctx, msg: err})
            return
        }
        responseSuc({ctx: ctx})

    } catch (err) {
        responseErr({ctx: ctx, msg: err})
    }
}


const checkFile = async (ctx) => {
    let {file_hash} = ctx.query
    if (!file_hash) {
        responseErr({ctx: ctx, msg: "请上传file_hash"})
        return
    }
    let {data, err} = await fileService.checkFile(file_hash)
    if (err) {
        responseErr({ctx: ctx, msg: err})
        return
    }
    responseSuc({ctx: ctx, data: {isHas:data.isHas,url:"http://127.0.0.1:3000"+data.url}})

}
const mergeFile = async (ctx) => {
    let { file_hash, file_name } = ctx.request.body
    if (!file_hash||!file_name){
        responseErr({ctx: ctx, msg: 'file_hash和file_name必填'})
        return
    }
    // 指定目录路径
    const targetDir = path.join( process.cwd(),uploadDir, file_hash);
    const targetPath = path.join(process.cwd(),'/public/uploads/file', file_hash+file_name);
    if (!fs.existsSync(targetDir)) {
        responseErr({ctx: ctx, msg: 'File chunks not found.'})
        return
    }
    try {
        // 获取分片文件并按顺序排序
        const chunks = fs.readdirSync(targetDir)
            .sort((a, b) => {
                const aIndex = parseInt(a.split('-')[0]);
                const bIndex = parseInt(b.split('-')[0]);
                return aIndex - bIndex;
            });

        const writableStream = fs.createWriteStream(targetPath);

        for (const chunk of chunks) {
            const chunkPath = path.resolve(targetDir, chunk);
            const chunkData = fs.readFileSync(chunkPath);
            writableStream.write(chunkData);
        }
        writableStream.end();
        // 删除临时目录
        // fs.rmdirSync(targetDir);
     let {err} =   await fileService.insertFileUrl({
            url: fileDir + '/' + file_hash+file_name,
            file_hash: file_hash
        })
        if (err){
            responseSuc({ctx: ctx, msg:err})
        }
        responseSuc({ctx: ctx, data: {url:"http://127.0.0.1:3000"+fileDir+'/'+file_hash+file_name}})
    }catch (e) {
        responseSuc({ctx: ctx, msg:"合并失败"})
    }


    }

    module.exports = {
        uploadFileSlice,
        mergeFile,
        checkFile
    }
